/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package compumundohipermegared;

import ConstantesProcotolo.Protocolo;
import java.io.*;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import seguridad.ManejadorCertificados;
import sun.security.x509.X509CertImpl;

/**
 * clase encarcada de enciarle un archivo a otro peer
 * @author asistente
 */
public class EnviadorArchivos extends Thread implements Serializable{
    
     /**
     * Indicador de versiÃ³n para la serializaciÃ³n
     */
    private static final long serialVersionUID = 300L;
    
    /**
     * El flujo de salida asociado con el canal de comunicaciÃ³n
     */
    private PrintWriter out;
    /**
     * El flujo de entrada asociado con el canal de comunicaciÃ³n
     */
    private BufferedReader in;
    private OutputStream outputStream;
    private InputStream inputStream;
    
    /**
     * este arrylist guarda las fotos que estÃ¡n en el equipo
     * se usa para responder a las consultas
     * debe ser lo mismo que tiene la clase CompuMundoHipermegaRed
     */
    private ArrayList<Foto> fotosEnMiEquipo;

    private Compumundohipermegared padre;
    /**
     * esta es la llave publica del que pide la foto
     */
    private PublicKey llavePublicaDelQuePide;
    /**
     * ruta donde estÃ¡ el certificado del que pide el certificado
     */
    private String rutaArchivoCertDelQuePide;
   
    EnviadorArchivos(PrintWriter out, BufferedReader in, OutputStream outputStream, InputStream inputStream, ArrayList<Foto> fotosEnMiEquipo, Compumundohipermegared padre) {
        this.out = out;
        this.in = in;
        this.fotosEnMiEquipo = fotosEnMiEquipo;
        this.outputStream = outputStream;
        this.inputStream = inputStream;
        this.padre = padre;
    }

    public void run( ) 
    {
        //boolean heTerminado = false;

        Foto fotoSolicitada = null;

        try 
        {
            String mensaje = in.readLine( );
            System.out.println( mensaje );

                ////////////////////
                /// certificado!!!!!
                /////////////////////
            recibirCertificado(mensaje);
            
            
                ////////////////////
                /// certificado!!!!!
                /////////////////////
            
            
                  ////////////////////
                /// ciframiento de la llave de mi archivo!!!!!
                /////////////////////
            enviarLlaveCifrada();
            mensaje = in.readLine();
            
            if( mensaje.startsWith( Protocolo.ENVIEME_LA_FOTO.toString( ) ) ) 
            {
                 
                // le envÃ­a el certificado               
                String nombreFoto = mensaje.split(":")[1];
                fotoSolicitada = buscarFoto(nombreFoto);
                System.out.println( "Estoy buscando en mis fotos la foto " + nombreFoto );
                if( fotoSolicitada == null ) 
                {
                    System.out.println("no la tengo");
                    out.println(Protocolo.NO_LA_TENGO.toString());
                } 
                else 
                {
                    System.out.println("ahi va el objeto...");
                    out.println(Protocolo.AHI_VA_EL_OBJETO.toString());
                    ObjectOutputStream oos = new ObjectOutputStream(outputStream);
                    oos.writeObject( fotoSolicitada );
                    oos.flush( );
                    System.out.println("ya lo envie");

                    System.out.println("ahi va el archivo...");

                    File myFile = new File(fotoSolicitada.getUbicacionArchivo());
                    
                    byte[] mybytearray = new byte[(int) myFile.length()];
                    
                    FileInputStream fis = new FileInputStream(myFile);
                    BufferedInputStream bis = new BufferedInputStream(fis);
                    bis.read(mybytearray, 0, mybytearray.length);
                    
                    // envio el tamanio del archivo 
                    out.println(Protocolo.AHI_VA_EL_ARCHIVO+":"+mybytearray.length);
                    System.out.println(Protocolo.AHI_VA_EL_ARCHIVO+":"+mybytearray.length);
                    outputStream.write(mybytearray,0,mybytearray.length);
                    outputStream.flush();
                    System.out.println("termine de enviar el archivo");
                    //////////////////////////////////////////
                    ///Firmaaaaaaaaa!!!!!!!!!!!
                    /////
                    
                    generarFirma(fotoSolicitada.getUbicacionArchivo());
                    enviarFirma();
                    enviarCertificado();
                    //////////////////////////////////////////
                    ///Firmaaaaaaaaa!!!!!!!!!!!
                    /////
                    bis.close();
                    
                    //enviarLlaveCifrada( );
                    out.close( );
                }
            }
        } 
        catch( Exception ex ) 
        {
            System.out.println( "Error de IO :" + ex.getMessage( ) );
            ex.printStackTrace( );
        }
    }
     public void enviarCertificado( )
    {     
        FileInputStream fis = null;
        try 
        {
            File myFile = new File("./data/"+padre.getNombreUsuario( ) +".cer" );
            byte[] mybytearray = new byte[(int) myFile.length()];
            out.println(Protocolo.AHI_VA_MI_CERTIFICADO.toString() + ":" + padre.getNombreUsuario( ) + ":" + mybytearray.length );
            System.out.println(Protocolo.AHI_VA_MI_CERTIFICADO.toString() + ":" + padre.getNombreUsuario( ) + ":" + mybytearray.length);
            fis = new FileInputStream(myFile);
            BufferedInputStream bis = new BufferedInputStream(fis);
            bis.read(mybytearray, 0, mybytearray.length);
            // envio el tamanio del archivo
           // out.println(Protocolo.AHI_VA_EL_ARCHIVO+":"+mybytearray.length);
            outputStream.write(mybytearray,0,mybytearray.length);
            outputStream.flush();
            System.out.println("ya lo envie");
        }
        catch(Exception ex) 
        {
            Logger.getLogger(Buscador.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }
     
    public void recibirCertificado(String mensaje) throws Exception
    {
        
                ////////////////////
                /// certificado!!!!!
                /////////////////////
                
                if(mensaje.startsWith(Protocolo.AHI_VA_MI_CERTIFICADO.toString()))
                {
                    System.out.println("Comienzo a recibir el certificado");
                    String rutaDestino = "./data/" + mensaje.split( ":" )[ 1 ]+".cer";
                    int tamanio = Integer.valueOf(mensaje.split(":")[2]);
                    int bytesRead;
                    int current = 0;
                    byte[] mybytearray = new byte[tamanio];
                    FileOutputStream fos = new FileOutputStream(rutaDestino);
                    
                    rutaArchivoCertDelQuePide=rutaDestino;

                    BufferedOutputStream bos = new BufferedOutputStream(fos);
                    do {
                        bytesRead = inputStream.read(mybytearray, current, (mybytearray.length - current));
                        System.out.println("He leido " + current + " bytes, y acabo de leer" + bytesRead);
                        if (bytesRead >= 0) {
                            current += bytesRead;
                        }
                    } while (bytesRead > 0);

                    System.out.println("Termine de recibir el certificado");
                    bos.write(mybytearray, 0, current);
                    bos.flush();


                    bos.close();
            
                }
               
    }
    /**
     * busca la foto con el nomrbe dado en al arraylist
     * @param fotosEnMiEquipo
     * @return 
     */
    private Foto buscarFoto(String nombreFoto) {

        for (int i = 0; i < fotosEnMiEquipo.size(); i++) {
            Foto foto = fotosEnMiEquipo.get(i);
            if (foto.getId().equals(nombreFoto)) {
                return foto;
            }
        }
        return null;
    }
    /**
     * 
     */
    private void enviarLlaveCifrada()
    {
        
        String miLlave = padre.contrasenaEscogida;
        X509CertImpl certitifadoDelQuePide = ManejadorCertificados.leerCertificado(rutaArchivoCertDelQuePide);
        llavePublicaDelQuePide = certitifadoDelQuePide.getPublicKey();
        System.out.println("llave original: " +miLlave);
        
        byte[] textoCifrado = ManejadorCertificados.bytesCifrarTextoConLlavePublica(llavePublicaDelQuePide, miLlave);
        
       
        String strBytes = "";
        for (int i = 0; i < textoCifrado.length; i++) {
            byte b = textoCifrado[i];
            strBytes+=b +";";
            
            System.out.print(strBytes+"\t");
        }
        
        System.out.println();
        out.println( Protocolo.AHI_VA_MI_LLAVE_SIMETRICA );
        System.out.println("llave simetrica enviada");
        out.println(strBytes);
        System.out.println("acabo de enviar el password");
    }

    private void generarFirma(String ubicacionArchivo) {
        String rutaLlavePrivada = "./data/"+padre.getNombreUsuario()+".llavePrivada";
        PrivateKey pk = ManejadorCertificados.cargarLlavePrivada(rutaLlavePrivada);
        
        ManejadorCertificados.firmarObjeto(ubicacionArchivo, pk);
    }

    private void enviarFirma() {
        FileInputStream fis = null;
        System.out.println("voy a mandar la firma");
        try 
        {
            
            File myFile = new File("./data/firma" );
            byte[] mybytearray = new byte[(int) myFile.length()];
           
            fis = new FileInputStream(myFile);
            BufferedInputStream bis = new BufferedInputStream(fis);
            bis.read(mybytearray, 0, mybytearray.length);
            // envio el tamanio del archivo
           // out.println(Protocolo.AHI_VA_EL_ARCHIVO+":"+mybytearray.length);
            out.println(Protocolo.AHI_VA_LA_FIRMA+":"+mybytearray.length);
            
            outputStream.write(mybytearray,0,mybytearray.length);
            outputStream.flush();
            System.out.println("ya lo envie");
        }
        catch(Exception ex) 
        {
            Logger.getLogger(Buscador.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }
}
